<!doctype html>
<html>
  <head>
    <title>Notifications: The Notification object exposes the expected properties.</title>
    <script src="../resources/testharness.js"></script>
    <script src="../resources/testharnessreport.js"></script>
  </head>
  <body>
    <script>
      // Tests that the Notification object exposes the properties per the
      // semantics defined by the specification. When the test is being ran
      // manually, grant Notification permission first.
      test(function () {
          assert_greater_than_equal(Notification.maxActions, 0);
          var oldMaxActions = Notification.maxActions;
          Notification.maxActions++;
          assert_equals(Notification.maxActions, oldMaxActions, 'Notification.maxActions should be immutable.');

          var options = {
                dir: "rtl",
                lang: "nl-NL",
                body: "Hallo, wereld!",
                tag: "notification",
                image: "http://localhost/image.jpg",
                icon: "http://localhost/my_icon.png",
                badge: "http://localhost/badge.png",
                timestamp: 621046800000,
                silent: true,
                requireInteraction: true,
                data: "my data",
                actions: []
            };

            var notification = new Notification("My Notification", options);

            assert_equals(notification.title, "My Notification");
            assert_equals(notification.dir, options.dir);
            assert_equals(notification.lang, options.lang);
            assert_equals(notification.body, options.body);
            assert_equals(notification.tag, options.tag);
            assert_equals(notification.image, options.image);
            assert_equals(notification.icon, options.icon);
            assert_equals(notification.badge, options.badge);
            assert_equals(notification.timestamp, options.timestamp);
            assert_true(notification.silent);
            assert_true(notification.requireInteraction);
            assert_equals(notification.data, options.data);
            assert_array_equals(notification.actions, options.actions);

            // The `actions` field should be immutable.
            assert_throws_js(TypeError, () => notification.actions.push(null));

            notification.actions.foo = 'bar';
            assert_false(notification.actions.hasOwnProperty('foo'));

            var emptyNotification = new Notification("My Notification");

            assert_equals(emptyNotification.title, "My Notification");
            assert_equals(emptyNotification.dir, "auto");
            assert_equals(emptyNotification.lang, "");
            assert_equals(emptyNotification.body, "");
            assert_equals(emptyNotification.tag, "");
            assert_equals(emptyNotification.image, "");
            assert_equals(emptyNotification.icon, "");
            assert_equals(emptyNotification.badge, "");
            assert_array_equals(emptyNotification.vibrate, []);
            assert_false(emptyNotification.silent);
            assert_false(emptyNotification.requireInteraction);
            assert_equals(emptyNotification.data, null);
            assert_array_equals(emptyNotification.actions, []);

            var timeDifference = Math.abs(Date.now() - emptyNotification.timestamp);
            assert_true(timeDifference < 16);  // 16 is not significant, just to reduce flakiness.

            var equalNotification = new Notification("My Notification", {
                vibrate: [50, 10, 50, 10, 50],
                data: { hello: "World!" }
            });

            // Test equality of the object attributes.
            assert_equals(equalNotification.data, equalNotification.data, '`data` object equality');
            assert_equals(equalNotification.vibrate, equalNotification.vibrate, '`vibrate` object equality');

            var serializedUrlNotification = new Notification("My Notification", {
                image: "https://example.com/image.jpg",
                icon: "https://example.com/icon.png",
                badge: "https://example.com/badge.png"
            });

            // Icon URLs should be returned in serialized form.
            assert_equals(serializedUrlNotification.image, "https://example.com/image.jpg");
            assert_equals(serializedUrlNotification.icon, "https://example.com/icon.png");
            assert_equals(serializedUrlNotification.badge, "https://example.com/badge.png");

            var noTagNotification = new Notification("My Notification"),
                emptyTagNotification = new Notification("My Notification", { tag: "" });

            // Setting an empty string as the tag should be equal to not setting the tag at all.
            assert_equals(noTagNotification.tag, emptyTagNotification.tag);

            var vibrateNotification = new Notification("My Notification", {
                vibrate: 1000
            });

            // vibrate pattern should be returned in serialized form.
            assert_array_equals(vibrateNotification.vibrate, [1000]);

            // The `vibrate` property should be immutable.
            assert_throws_js(TypeError, () => vibrateNotification.vibrate.push(1000));

            vibrateNotification.vibrate[0] = 2000;
            assert_equals(vibrateNotification.vibrate[0], 1000);

            // Tests that it must be a valid vibration sequence.
            var pattern = new Array(100, 200, 300);
            var sequenceVibrateNotification = new Notification("My Notification", {
                vibrate: pattern
            });
            assert_array_equals(sequenceVibrateNotification.vibrate, pattern);

            // Invalid vibrate pattern should be reset to 0.
            var invalidVibrateNotification = new Notification("My Notification", {
                vibrate: [100, 200, "invalid"]
            });
            assert_array_equals(invalidVibrateNotification.vibrate, [100, 200, 0]);

            // Notification actions should only be supported for persistent notifications.
            assert_throws_js(TypeError, function() {
                new Notification("My Notification", {
                    actions: [{ action: "foo", title: "Foo" }]
                });
            }, 'Providing non-empty `actions` for a non-persistent notification should throw a TypeError.');

            // Notification showTrigger should only be supported for persistent notifications.
            assert_throws_js(TypeError, function() {
                new Notification("My Notification", {
                    showTrigger: new TimestampTrigger(Date.now())
                });
            }, 'Providing non-empty `showTrigger` for a non-persistent notification should throw a TypeError.');

            // Notification actions should only support the placeholder attribute if they are type text.
            assert_throws_js(TypeError, function() {
                new Notification("My Notification", {
                    actions: [{ action: "foo", title: "Foo", placeholder: "I'm sorry, Dave." }]
                });
            }, 'Providing a placeholder for an action that is not type text should throw a TypeError.');

            // Notification actions should not accept invalid types.
            assert_throws_js(TypeError, function() {
                new Notification("My Notification", {
                    actions: [{ type: "blah", action: "foo", title: "Foo" }]
                });
            }, 'Providing an invalid type for an action should throw a TypeError.');

      }, 'Checks the properties exposed on the Notification object.');
    </script>
  </body>
</html>
